import com.test.component.*;
import com.test.controller.*;
import com.test.model.Student;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;


public class App {
    public static void main(String[] args) {

      //  test01();
       // System.out.println("***");
      //  test02();

        //使用注解的方式
      //  test03();

     //   test04();

     //   test05();

      // test06();
        /*
        * 方法 @Bean
        * */
//        test07();

        /*
        * 重命名 @Bean
        * */
       // test08();

        /*
        * 获取Bean对象
        * 属性注入
        * */
      //  test09();

        /*
        * Setter注入
        * */
      //  test10();

        /*
        * 构造方法注入
        * */
        //test11();

        /*
        Resource注入

         */
     //   test12();

        /*
        *同⼀类型多个 @Bean 报错
        * */

       // test13();

        /*
        * Bean作用域的一个演示案例
        * */
      //  test14();

        /*
        * Bean作用域的 prototype 设置作用域
        * */
        //test15();
        /*
        用代码 查看 spring 的生命周期
         */
        //test16();

        /*
        先设置属性,再初始化 的代码演示
        */
        test17();
    }

    private static void test17() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        DComponent dComponent = context.getBean("DComponent",DComponent.class);

        //先设置属性,再初始化 的代码演示
        /*
        执行了 F的 PostConstruct
        执行了 E的 PostConstruct
        执行了 D的 PostConstruct
        * */


        /*
        *   执行了 F的 PostConstruct
            执行了 E的 PostConstruct
            hi EComponent
            执行了 D的 PostConstruct
        * */
    }

    private static void test16() {
      ClassPathXmlApplicationContext applicationContext =
              new ClassPathXmlApplicationContext("springConfig.xml");
        BeanLifeComponent beanLifeComponent = applicationContext.getBean("myComponent",BeanLifeComponent.class);
        System.out.println("使用Bean");
        //销毁Bean
        applicationContext.destroy();

    }

    // Bean作用域的 prototype 设置作用域
    private static void test15() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        UserController uc = context.getBean("userController",UserController.class);
        uc.getUser();

        UserAdviceController ua = context.getBean("userAdviceController",UserAdviceController.class);
        ua.getUser();


        //每次对该作用域下的Bean的请求都会创建新的实例，获取Bean以及装配Bean都是新的对象实例
        /*
        张三：user1 : UserBean(id=1, name=张三, password=123456)
        李四：u : UserBean(id=1, name=李四, password=123456)
        王五：user1 : UserBean(id=1, name=张三, password=123456)
        * */
    }


    // Bean作用域的一个演示案例
    private static void test14() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        UserController uc = context.getBean("userController",UserController.class);
        uc.getUser();

       UserAdviceController ua = context.getBean("userAdviceController",UserAdviceController.class);
       ua.getUser();

       //王五：理应去拿张三的公共部分的 内容，却拿到了 李四 被修改后的内容

        //原因：Bean默认情况下是单例状态，也就是所有的人使用的对象都是同一个对象

       /*
       * 张三：user1 : UserBean(id=1, name=张三, password=123456)
        李四：u : UserBean(id=1, name=李四, password=123456)
        王五：user1 : UserBean(id=1, name=李四, password=123456)
       *
       * */
    }

    //同⼀类型多个 @Bean 报错
    private static void test13() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        StudentController5 student = context.getBean("studentController5", StudentController5.class);
        student.sayHi();
    }

    //Resource注入
    private static void test12() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        StudentController4 student = context.getBean("studentController4", StudentController4.class);
        student.sayHi();
    }

    //构造方法注入
    private static void test11() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        StudentController3 student = context.getBean("studentController3", StudentController3.class);
        student.sayHi();
    }

    //Setter注入
    private static void test10() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        StudentController2 student = context.getBean("studentController2", StudentController2.class);
        student.sayHi();
    }

    //属性注入
    private static void test09() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        StudentController student = context.getBean("studentController", StudentController.class);
        student.sayHi();
    }

    private static void test08() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        Student student = context.getBean("s2", Student.class);
     //  Student student = context.getBean("reBack", Student.class);

        System.out.println(student);
    }

    //方法 @Bean
    private static void test07() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        Student student = context.getBean("reBack", Student.class);
        System.out.println(student);
    }


    private static void test06() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        UsrComponent  usrComponent = context.getBean("usrComponent", UsrComponent.class);
        System.out.println(usrComponent.sayHi());
    }


    /*
    *
    * */
    private static void test05() {
     /*   ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
       BController song = context.getBean("bController", BController.class);
        System.out.println(song.say());*/

        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        BController song = context.getBean("BController", BController.class);
        System.out.println(song.say());
    }

    //如果类名首字母是小写,还能从Spring中获取Bean吗?
    //可以的
    //控制台输出: hi aController
    private static void test04() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        aController song = context.getBean("aController", aController.class);
        System.out.println(song.say());
    }

    private static void test03() {
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        SongController song = context.getBean("songController", SongController.class);
        System.out.println(song.say());

    }


    //比较老的一种
    private static void test02() {
        BeanFactory factory = new XmlBeanFactory(new ClassPathResource("springConfig.xml"));
        System.out.println("context");

        //2.从spring中取出Bean对象
        User user = factory.getBean("user", User.class);
        //3.使用Bean(可选)
        System.out.println(user.sayHi());

    }

    //现在用的
    private static void test01() {
        //1.得到spring 对象
        ApplicationContext context = new ClassPathXmlApplicationContext("springConfig.xml");
        System.out.println("context");
        //----------------在没有创建对象的情况下,就可以使用bean对象

        //2.从spring中取出Bean对象
        User user = context.getBean("user", User.class);
        //3.使用Bean(可选)
        System.out.println(user.sayHi());

    }


}
